/*
 * Copyright (c) 2023-2024. Compose Cupertino project and open source contributors.
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 *
 */

package com.gitee.wsl.compose.ui.section.lazylist

import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.heightIn
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.LocalContentColor
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.ProvideTextStyle
import androidx.compose.runtime.Composable
import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.runtime.Stable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.Dp
import com.gitee.wsl.compose.ui.section.CupertinoSectionDefaults
import com.gitee.wsl.compose.ui.section.CupertinoSectionTokens


@Stable
sealed interface LazySectionScope  {

    /**
     * Plain section item without additional controls
     *
     * @param key optional key for item.
     * @param contentType optional content type for item.
     * @param dividerPadding start divider padding
     * @param content item content
     *
     * @see items
     * */
    fun item(
        key: Any? = null,
        contentType: Any? = null,
        dividerPadding : Dp = CupertinoSectionDefaults.DividerPadding,
        content: @Composable (padding : PaddingValues) -> Unit
    )
}


/**
 * Section control with [CupertinoSwitch]
 *
 * @param checked if switch is checked
 * @param onCheckedChange action performed when switch changes checked state
 * @param key optional key for item.
 * @param enabled if label is clickable.
 * @param icon icon displayed at the start of this item. [CupertinoLinkIcon] is often used for it.
 * @param dividerPadding start divider padding. By default inferred from presence of [icon].
 * @param interactionSource label interaction source.
 * @param thumbContent content of the [CupertinoSwitch] thumb.
 * @param title switch title.
 *
 * @see CupertinoSwitch
 * @see CupertinoLinkIcon
 * @see link
 * */
/*fun LazySectionScope.switch(
    checked: Boolean,
    onCheckedChange: (Boolean) -> Unit,
    modifier: Modifier = Modifier,
    key: Any? = null,
    enabled: Boolean = true,
    colors : CupertinoSwitchColors ?= null,
    icon: (@Composable () -> Unit)? = null,
    dividerPadding: Dp = if (icon != null)
        CupertinoSectionDefaults.DividerPaddingWithIcon
    else CupertinoSectionDefaults.DividerPadding,
    interactionSource: MutableInteractionSource? = null,
    thumbContent: @Composable (() -> Unit)? = null,
    title: @Composable () -> Unit,
) = row(
    key = key,
    contentType = ContentTypeToggle,
    dividerPadding = dividerPadding,
    title = {
        if (icon != null) {
            Row(
                verticalAlignment = Alignment.CenterVertically,
                horizontalArrangement = Arrangement
                    .spacedBy(CupertinoSectionTokens.HorizontalPadding)
            ) {
                icon.invoke()
                title.invoke()
            }
        } else {
            title.invoke()
        }
    },
    endContent = {
        Switch(
            modifier = modifier,
            enabled = enabled,
            checked = checked,
            thumbContent = thumbContent,
            colors = colors ?: CupertinoSwitchDefaults.colors(),
            onCheckedChange = onCheckedChange,
            interactionSource = interactionSource ?: remember { MutableInteractionSource() }
        )
    }
)*/

/*
fun LazySectionScope.datePicker(
    state: CupertinoDatePickerState,
    expanded : Boolean,
    onExpandedChange : (Boolean) -> Unit,
    modifier: Modifier = Modifier,
    style : DatePickerStyle? = null,
    enabled: Boolean = true,
    icon: (@Composable () -> Unit)? = null,
    dividerPadding: Dp = if (icon != null)
        CupertinoSectionDefaults.DividerPaddingWithIcon
    else CupertinoSectionDefaults.DividerPadding,
    buttonColor : Color = Color.Unspecified,
    button : @Composable (
        buttonModifier : Modifier,
        titleModifier: Modifier,
        text : String
    ) -> Unit = { buttonModifier, titleModifier, text ->
        CupertinoSectionDefaults.PickerButton(
            modifier = buttonModifier,
            containerColor = buttonColor,
            expanded = expanded,
            title = {
                CupertinoText(
                    text = text,
                    modifier = titleModifier
                )
            }
        )
    },
    title: @Composable () -> Unit,
) = picker(
    expanded = expanded,
    enabled = enabled,
    onExpandedChange = onExpandedChange,
    contentType = ContentTypeDatePicker,
    dividerPadding = dividerPadding,
    title = title,
    button = button,
    text = {
        val locale = defaultLocale()
        remember {
            derivedStateOf {
                state.stateData.calendarModel
                    .getCanonicalDate(state.selectedDateMillis)
                    .format(
                        state.stateData.calendarModel,
                        CupertinoDatePickerDefaults.YearAbbrMonthDaySkeleton,
                        locale
                    )
            }
        }.value
    },
    content = {
        CupertinoDatePicker(
            modifier = modifier
                .fillMaxWidth()
                .padding(horizontal = 6.dp),
            state = state,
            style = style ?: DatePickerStyle.Pager()
        )
    }
)


fun LazySectionScope.timePicker(
    state: CupertinoTimePickerState,
    expanded: Boolean,
    onExpandedChange: (Boolean) -> Unit,
    modifier: Modifier = Modifier,
    enabled: Boolean = true,
    icon: @Composable() (() -> Unit)? = null,
    dividerPadding: Dp = if (icon != null)
        CupertinoSectionDefaults.DividerPaddingWithIcon
    else CupertinoSectionDefaults.DividerPadding,
    buttonColor : Color = Color.Unspecified,
    button: @Composable (buttonModifier: Modifier, titleModifier: Modifier, text: String) -> Unit = { buttonModifier, titleModifier, text ->
        CupertinoSectionDefaults.PickerButton(
            modifier = buttonModifier,
            containerColor = buttonColor,
            expanded = expanded,
            title = {
                CupertinoText(
                    text = text,
                    modifier = titleModifier
                )
            }
        )
    },
    title: @Composable () -> Unit,
) = picker(
    enabled = enabled,
    expanded = expanded,
    onExpandedChange = onExpandedChange,
    contentType = ContentTypeTimePicker,
    dividerPadding = dividerPadding,
    title = title,
    button = button,
    text = {
        remember(state) {
            derivedStateOf {
                "${state.hour % if (state.is24Hour) 24 else 12}:${state.minute.toStringWithLeadingZero()}" + when {
                    state.is24Hour -> ""
                    state.isEvening -> " PM"
                    else -> " AM"
                }
            }
        }.value
    },
    content = {
        CupertinoTimePicker(
            modifier = modifier.fillMaxWidth(),
            state = state,
        )
    }
)*/

/*
fun LazySectionScope.textField(
    value: String,
    onValueChange: (String) -> Unit,
    modifier: Modifier = Modifier,
    enabled: Boolean = true,
    readOnly: Boolean = false,
    textStyle: TextStyle? = null,
    placeholder: @Composable (() -> Unit)? = null,
    trailingIcon: @Composable ((InteractionSource) -> Unit)? = {
        val focused by it.collectIsFocusedAsState()

        val updatedValueChange by rememberUpdatedState(onValueChange)

        CupertinoSectionDefaults.TextFieldClearButton(
            visible = focused && value.isNotEmpty(),
            onClick = {
                updatedValueChange.invoke("")
            }
        )
    },
    visualTransformation: VisualTransformation = VisualTransformation.None,
    keyboardOptions: KeyboardOptions = KeyboardOptions.Default,
    keyboardActions: KeyboardActions = KeyboardActions.Default,
    singleLine: Boolean = false,
    maxLines: Int = if (singleLine) 1 else Int.MAX_VALUE,
    minLines: Int = 1,
    interactionSource: MutableInteractionSource? = null,
    dividerPadding: Dp = CupertinoSectionDefaults.DividerPadding,
    colors: CupertinoTextFieldColors? = null,
) = row(
    key = null,
    contentType = ContentTypeTextField,
    dividerPadding = dividerPadding,
    title = {
        ProvideTextStyle(
            textStyle ?: MaterialTheme.typography.bodyMedium
        ) {
            Box(
                contentAlignment = Alignment.CenterStart
            ) {

                val actualInteractionSource = interactionSource ?: remember {
                    MutableInteractionSource()
                }

                CupertinoTextField(
                    value = value,
                    onValueChange = onValueChange,
                    modifier = modifier.fillMaxWidth(),
                    colors = colors ?: CupertinoTextFieldDefaults.colors(),
                    enabled = enabled,
                    readOnly = readOnly,
                    visualTransformation = visualTransformation,
                    keyboardOptions = keyboardOptions,
                    keyboardActions = keyboardActions,
                    singleLine = singleLine,
                    maxLines = maxLines,
                    minLines = minLines,
                    placeholder = placeholder,
                    interactionSource = actualInteractionSource,
                    trailingIcon = trailingIcon?.let {
                        { it(actualInteractionSource) }
                    }
                )
            }
        }
    },
)*/

/**
 * Shortcut for adding a bunch of [LazySectionScope.item]s to the section
 *
 * @param count items count.
 * @param key optional key for specific item.
 * @param contentType optional content type for specific item.
 * @param dividerPadding start divider padding
 * @param content item content
 * */
inline fun LazySectionScope.items(
    count : Int,
    key: (Int) -> Any? = { null },
    contentType: (Int) -> Any? = { null },
    dividerPadding : Dp = CupertinoSectionDefaults.DividerPadding,
    crossinline content: @Composable (idx : Int, padding : PaddingValues) -> Unit
) = repeat(count) {
    item(
        key = key(it),
        contentType = contentType(it),
        dividerPadding = dividerPadding,
    ) { pv ->
        content(it, pv)
    }
}

/**
 * Shortcut for adding a bunch of [LazySectionScope.item]s to the section
 *
 * @param items items list.
 * @param key optional key for specific item.
 * @param contentType optional content type for specific item.
 * @param dividerPadding start divider padding
 * @param content item content
 * */
inline fun <T> LazySectionScope.items(
    items : Collection<T>,
    key: (T) -> Any? = { null },
    contentType: (T) -> Any? = { null },
    dividerPadding : Dp = CupertinoSectionDefaults.DividerPadding,
    crossinline content: @Composable (item : T, padding : PaddingValues) -> Unit
) = items.forEach {
    item(
        key = key(it),
        contentType = contentType(it),
        dividerPadding = dividerPadding,
    ) { pv ->
        content(it, pv)
    }
}




 fun LazySectionScope.row(
    key: Any?,
    contentType: Any?,
    dividerPadding: Dp,
    modifier: @Composable () -> Modifier = { Modifier },
    endContent: @Composable () -> Unit = {},
    title: @Composable () -> Unit
) = item(
    key = key,
    contentType = contentType,
    dividerPadding = dividerPadding
) {
    CompositionLocalProvider(
        LocalContentColor provides MaterialTheme.colorScheme.primary
    ) {
        ProvideTextStyle(MaterialTheme.typography.bodyMedium) {
            Row(
                modifier = modifier()
                    .heightIn(min = CupertinoSectionTokens.MinHeight)
                    .fillMaxWidth()
                    .padding(it),
                verticalAlignment = Alignment.CenterVertically,
//        horizontalArrangement = Arrangement.spacedBy(CupertinoSectionTokens.SplitPadding)
            ) {
                Box(Modifier.weight(1f)) {
                    title()
                }
                CompositionLocalProvider(
                    LocalContentColor provides MaterialTheme.colorScheme.secondary,
                    endContent
                )
            }
        }
    }
}


internal class SectionItem(
    val key: Any? = null,
    val contentType: Any? = null,
    val dividerPadding: Dp?,
    val content: @Composable (PaddingValues) -> Unit,
)

@Stable
internal class LazySectionScopeImpl : LazySectionScope {

    val items: List<SectionItem>
        get() = _items

    private val _items = mutableListOf<SectionItem>()

    internal fun item(
        key: Any? = null,
        contentType: Any? = null,
        dividerPadding: Dp? = null,
        minHeight: Dp,
        content: @Composable (PaddingValues) -> Unit,
    ) {
        _items += SectionItem(
            key = key,
            contentType = contentType,
            content = {
                ProvideTextStyle(MaterialTheme.typography.bodyMedium) {
                    Box(
                        modifier = Modifier
                            .heightIn(min = minHeight)
                            .fillMaxWidth(),
                        contentAlignment = Alignment.CenterStart
                    ) {
                        content(it)
                    }
                }
            },
            dividerPadding = dividerPadding
        )
    }

    override fun item(
        key: Any?,
        contentType: Any?,
        dividerPadding: Dp,
        content: @Composable (PaddingValues) -> Unit
    ) {
        item(
            key = key,
            contentType = contentType,
            dividerPadding = dividerPadding,
            minHeight = CupertinoSectionTokens.MinHeight,
            content = content
        )
    }

}



object ContentTypeLabel
 object ContentTypeToggle
 object ContentTypeDatePicker
 object ContentTypeTimePicker

 object ContentTypeTextField